package main

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	log "github.com/sirupsen/logrus"
)

type T6006GPS struct {
	Latitude  string `json:"latitude"`
	Longitude string `json:"longitude"`
	Province  string `json:"province"`
	TrueTrack string `json:"true_track"`
	SpeedKmh  string `json:"speed_kmh"`
}

type T6006 struct {
	ISP     string                 `json:"isp"`
	Signal  int                    `json:"signal"`
	Service string                 `json:"service"`
	Yaw     string                 `json:"yaw"`
	Time    string                 `json:"time"`
	Depth   string                 `json:"depth"`
	Mac     string                 `json:"mac"`
	Pitch   string                 `json:"pitch"`
	Roll    string                 `json:"roll"`
	GPS     T6006GPS               `json:"gps"`
	JSON    map[string]interface{} `json:"json"`
}

func convertToString(val interface{}) string {
	switch v := val.(type) {
	case string:
		return v
	default:
		return fmt.Sprintf("%v", val)
	}
}

func convertToInt(val interface{}) int {
	switch v := val.(type) {
	case uint8:
		return int(v)
	case int8:
		return int(v)
	case int:
		return v
	case string:
		n, _ := strconv.ParseInt(v, 0, 64)
		return int(n)
	default:
		return 0
	}
}

func formatSibo(data map[string]interface{}) T6006 {
	m := T6006{}
	m.ISP = convertToString(data["isp"])
	m.Signal = convertToInt(data["signal"])
	m.Service = convertToString(data["service"])
	m.Yaw = convertToString(data["yaw"])
	m.Depth = convertToString(data["depth"])
	m.Pitch = convertToString(data["pitch"])
	m.Roll = convertToString(data["roll"])
	m.Mac = convertToString(data["mac"])
	m.Time = convertToString(data["time"])
	json := map[string]interface{}{}
	for k, v := range data {
		json[k] = v
	}
	caou := make([]string, 6)
	caou[0] = fmt.Sprintf("%f", data["主机 1#缸排气温度 TE1601A"])
	caou[1] = fmt.Sprintf("%f", data["主机 2#缸排气温度 TE1602A"])
	caou[2] = fmt.Sprintf("%f", data["主机 3#缸排气温度 TE1603A"])
	caou[3] = fmt.Sprintf("%f", data["主机 4#缸排气温度 TE1604A"])
	caou[4] = fmt.Sprintf("%f", data["主机 5#缸排气温度 TE1605A"])
	caou[5] = fmt.Sprintf("%f", data["主机 6#缸排气温度 TE1606A"])
	json["ME"] = []map[string]interface{}{
		{
			"REV":   fmt.Sprintf("%f", data["主机转速 SE1704C"]),
			"MEWOT": "0",
			"MEOIP": fmt.Sprintf("%f", data["主机滑油进机压力 PT1224A"]),
			"MEOT":  fmt.Sprintf("%f", data["主机滑油进机温度 TE1224"]),
			"PBAP":  fmt.Sprintf("%f", data["主机增压空气压力 PT1331A"]),
			"ACOT":  "0",
			"CAOU":  caou,
		},
	}
	json["DEPTHDEV"] = []map[string]string{
		{
			"Depth": getString(data, "depth"),
		},
	}
	m.JSON = json
	m.GPS = T6006GPS{
		Longitude: convertToString(data["longitude"]),
		Latitude:  convertToString(data["latitude"]),
		SpeedKmh:  convertToString(data["speed_kmh"]),
		TrueTrack: convertToString(data["true_track"]),
		Province:  convertToString(data["province"]),
	}
	return m
}

func assertMap(m interface{}) map[string]interface{} {
	switch v := m.(type) {
	case map[string]interface{}:
		return v
	default:
		return map[string]interface{}{}
	}
}

func getString(data map[string]interface{}, path string) string {
	v, ok := data[path]
	if !ok {
		return ""
	}
	switch v1 := v.(type) {
	case string:
		return v1
	default:
		return fmt.Sprintf("%v", v)
	}
}

func formatCanparse(data map[string]interface{}) T6006 {
	log.WithFields(log.Fields{"data": data, "name": "formatCanparse"}).Info("format")
	m := T6006{}
	m.ISP = convertToString(data["isp"])
	m.Signal = convertToInt(data["signal"])
	m.Service = convertToString(data["service"])
	m.Yaw = convertToString(data["yaw"])
	m.Depth = convertToString(data["Depth"])
	m.Pitch = convertToString(data["pitch"])
	m.Roll = convertToString(data["roll"])
	m.Mac = convertToString(data["mac"])
	m.Time = convertToString(data["time"])
	m.Time = formatTime(m.Time)
	// json := data["json"]
	// m.JSON = assertMap(json)
	js := map[string]interface{}{
		"ME": []map[string]string{
			{
				"REV":   getString(data, "ME1_REV"),
				"MEWOT": getString(data, "ME1_MEWOT"),
				"MEOIP": getString(data, "ME1_MEOIP"),
				"MEOT":  getString(data, "ME1_MEOT"),
				"MEAP":  getString(data, "ME1_MEAP"),
				"ACOT":  getString(data, "ME1_ACOT"),
				"METOP": getString(data, "ME1_METOP"),
				"MPEL":  getString(data, "ME1_MPEL"),
				"MEFR":  getString(data, "ME1_MEFR"),
				"METOT": getString(data, "ME1_METOT"),
			},
			{
				"REV":   getString(data, "ME2_REV"),
				"MEWOT": getString(data, "ME2_MEWOT"),
				"MEOIP": getString(data, "ME2_MEOIP"),
				"MEOT":  getString(data, "ME2_MEOT"),
				"MEAP":  getString(data, "ME2_MEAP"),
				"ACOT":  getString(data, "ME2_ACOT"),
				"METOP": getString(data, "ME2_METOP"),
				"MPEL":  getString(data, "ME2_MPEL"),
				"MEFR":  getString(data, "ME2_MEFR"),
				"METOT": getString(data, "ME2_METOT"),
			},
		},
		"WindSPD":   data["WindSpeed"],
		"WindAngle": data["WindAngle"],
		"DEPTHDEV": []map[string]string{
			{
				"Depth": getString(data, "Depth"),
			},
		},
	}
	m.JSON = js
	m.GPS = T6006GPS{
		Longitude: convertToString(data["longitude"]),
		Latitude:  convertToString(data["latitude"]),
		SpeedKmh:  convertToString(data["speed_kmh"]),
		TrueTrack: convertToString(data["true_track"]),
		Province:  convertToString(data["province"]),
	}
	return m
}

func formatGPSOnly(data map[string]interface{}) T6006 {
	log.WithFields(log.Fields{"data": data, "name": "formatGPSOnly"}).Info("format")
	m := T6006{}
	m.ISP = convertToString(data["isp"])
	m.Signal = convertToInt(data["signal"])
	m.Service = convertToString(data["service"])
	m.Yaw = convertToString(data["yaw"])
	m.Depth = convertToString(data["Depth"])
	m.Pitch = convertToString(data["pitch"])
	m.Roll = convertToString(data["roll"])
	m.Mac = convertToString(data["mac"])
	m.Time = convertToString(data["time"])
	m.JSON = map[string]interface{}{}
	m.GPS = T6006GPS{
		Longitude: convertToString(data["longitude"]),
		Latitude:  convertToString(data["latitude"]),
		SpeedKmh:  convertToString(data["speed_kmh"]),
		TrueTrack: convertToString(data["true_track"]),
		Province:  convertToString(data["province"]),
	}
	return m
}

func formatTime(s string) string {
	fmt.Printf("time = %s len = %d\n", s, len(s))
	if strings.HasSuffix(s, "Z") {
		t, err := time.Parse(time.RFC3339Nano, s)
		if err != nil {
			return ""
		}
		return t.Local().Format("2006-01-02T15:04:05")
	}
	return s
}
